
#include "EntityManager.h"
#include "Entity.h"
#include "Tank.h"
#include "Tower.h"
#include "Spawnpoint.h"
#include "Bullet.h"
#include "Enemy.h"
#include "../../SGD Wrappers/CSGD_TextureManager.h"
#include <cassert>
#include <math.h>


//Singleton accessor
EntityManager* EntityManager::GetInstance()
{ 
	static EntityManager instance;
	return &instance;
}


//Constructor
EntityManager::EntityManager(void)
{
}


//Create a new entity, add it to the entity list, and return a pointer to it
Entity* EntityManager::CreateEntity(EntityType entityType, float x, float y)
{
	Entity* e = nullptr;
	switch (entityType)
	{
	case ENTITY_TANK:
		e = new Tank();
		break;
	case ENTITY_TOWER:
		e = new Tower();
		break;
	case ENTITY_BULLET:
		e = new Bullet();
		break;
	case ENTITY_ENEMY:
		e = new Enemy();
		break;
	case ENTITY_SPAWNPOINT:
		e = new Spawnpoint();
		break;
	}
	e->entityType = entityType;
	e->x = x;
	e->y = y;
	e->isAlive = true;
	e->rotation = 0.0f;
	e->velocityX = 0.0f;
	e->velocityY = 0.0f;

	entityList.push_back(e);
	return e;
}


//Remove references to all entities
void EntityManager::Shutdown(void)
{
	for (iterator = entityList.begin(); iterator != entityList.end(); ++iterator)
	{
		(*iterator)->isAlive = false;
		(*iterator)->RemoveReference();
		(*iterator) = nullptr;
	}
	entityList.clear();
}


//Return a list of entities near a point
list<Entity*> EntityManager::FindEntitiesInRange(float x, float y, float range)
{
	list<Entity*> entitiesInRange;
	list<Entity*>::iterator iterator2;
	for (iterator2 = entityList.begin(); iterator2 != entityList.end(); ++iterator2)
	{
		float distance = sqrt(((*iterator2)->x - x)*((*iterator2)->x - x) + ((*iterator2)->y - y)*((*iterator2)->y - y));
		if (distance <= range)
		{
			entitiesInRange.push_back(*iterator2);
		}
	}
	return entitiesInRange;
}


//Update
void EntityManager::Update(float dt)
{
	//Update living entities
	int deadEntityCount = 0;
	for (iterator = entityList.begin(); iterator != entityList.end(); ++iterator)
	{
		if ((*iterator)->isAlive == true)
			(*iterator)->Update(dt);
		else
			deadEntityCount++;
	}

	//Clear dead entities
	for (int i = 0; i < deadEntityCount; ++i)
	{
		for (iterator = entityList.begin(); iterator != entityList.end(); ++iterator)
		{
			if ((*iterator)->isAlive == false)
			{
				(*iterator)->RemoveReference();
				entityList.remove(*iterator);
				break;
			}
		}
	}
}


//Render all living entities
void EntityManager::Render(void)
{
	for (iterator = entityList.begin(); iterator != entityList.end(); ++iterator)
	{
		if ((*iterator)->isAlive == true)
			(*iterator)->Render();
	}
}
